/*
 * @author: liubing
 * @Date: 2020-11-30 15:09:47
 * @desc: 
 */
    var canvasElement=document.getElementById('webgl');
    var gl=canvasElement.getContext('webgl');
    //顶点着色器源码
    var vertexShaderSource = '' +
        //attribute声明vec4类型变量apos
        'attribute vec4 apos;'+
        'attribute vec4 a_color;' +//attribute声明顶点颜色变量
        /**用于光照计算的变量a_normal、u_lightColor、u_lightDirection**/
        'attribute vec4 a_normal;' +//法向量变量
        'uniform vec3 u_lightColor;' + //uniform声明平行光颜色变量
        'uniform vec3 u_lightDirection;' + //平行光方向
        /**uniform声明旋转矩阵变量mx、my**/
        'uniform mat4 mx;'+//绕x轴旋转矩阵
        'uniform mat4 my;'+//绕y轴旋转矩阵
        'uniform mat4 Tx;'+//沿着x轴平移矩阵
        'varying vec4 v_color;'+//varying声明顶点颜色插值后变量
        'void main(){' +
        // 平移矩阵Tx、旋转矩阵mx、旋转矩阵my连乘
        '   gl_Position = Tx*mx*my*apos;' +
        // 顶点法向量归一化
        '  vec3 normal = normalize((mx*my*a_normal).xyz);' +
        // 计算平行光方向向量和顶点法向量的点积
        '  float dot = max(dot(u_lightDirection, normal), 0.0);' +
        // 计算平行光方向向量和顶点法向量的点积
        '  vec3 reflectedLight = u_lightColor * a_color.rgb * dot;' +
        //颜色插值计算
        '  v_color = vec4(reflectedLight, a_color.a);' +
        '}';
    //片元着色器源码
    var fragShaderSource = '' +
        'precision lowp float;' +//所有float类型数据的精度是lowp
        'varying vec4 v_color;'+//接收顶点着色器中v_color数据
        'void main(){' +
        '   gl_FragColor = v_color;' +
        '}';
    //初始化着色器

function main() {
    var program = initShader(gl,vertexShaderSource,fragShaderSource);
    /**
     * 从program对象获取相关的变量
     * attribute变量声明的方法使用getAttribLocation()方法
     * uniform变量声明的方法使用getAttribLocation()方法
     **/
    var aposLocation = gl.getAttribLocation(program,'apos');
    var a_color = gl.getAttribLocation(program,'a_color');
    var a_normal = gl.getAttribLocation(program,'a_normal');
    var u_lightColor = gl.getUniformLocation(program,'u_lightColor');
    var u_lightDirection = gl.getUniformLocation(program,'u_lightDirection');
    /**从program对象获得旋转矩阵变量mx、my地址**/
    var mx = gl.getUniformLocation(program,'mx');
    var my = gl.getUniformLocation(program,'my');
    var Tx = gl.getUniformLocation(program,'Tx');
    /**
     * 给平行光传入颜色和方向数据，RGB(1,1,1),单位向量(x,y,z)
     **/
    gl.uniform3f(u_lightColor, 1.0, 1.0, 1.0);
    //保证向量(x,y,z)的长度为1，即单位向量
    var x = 1/Math.sqrt(15), y = 2/Math.sqrt(15), z = 3/Math.sqrt(15);
    gl.uniform3f(u_lightDirection,x,y,-z);
    /**
     创建顶点位置数据数组data,Javascript中小数点前面的0可以省略
     **/
    var data=new Float32Array([
        .3,.3,.3,-.3,.3,.3,-.3,-.3,.3,.3,.3,.3,-.3,-.3,.3,.3,-.3,.3,      //面1
        .3,.3,.3,.3,-.3,.3,.3,-.3,-.3,.3,.3,.3,.3,-.3,-.3,.3,.3,-.3,      //面2
        .3,.3,.3,.3,.3,-.3,-.3,.3,-.3,.3,.3,.3,-.3,.3,-.3,-.3,.3,.3,      //面3
        -.3,.3,.3,-.3,.3,-.3,-.3,-.3,-.3,-.3,.3,.3,-.3,-.3,-.3,-.3,-.3,.3,//面4
        -.3,-.3,-.3,.3,-.3,-.3,.3,-.3,.3,-.3,-.3,-.3,.3,-.3,.3,-.3,-.3,.3,//面3
        .3,-.3,-.3,-.3,-.3,-.3,-.3,.3,-.3,.3,-.3,-.3,-.3,.3,-.3,.3,.3,-.3 //面6
    ]);
    /**
     创建顶点颜色数组colorData
     **/
    var colorData = new Float32Array([
        1,0,0, 1,0,0, 1,0,0, 1,0,0, 1,0,0, 1,0,0,//红色——面1
        1,0,0, 1,0,0, 1,0,0, 1,0,0, 1,0,0, 1,0,0,//红色——面2
        1,0,0, 1,0,0, 1,0,0, 1,0,0, 1,0,0, 1,0,0,//红色——面3
        1,0,0, 1,0,0, 1,0,0, 1,0,0, 1,0,0, 1,0,0,//红色——面4
        1,0,0, 1,0,0, 1,0,0, 1,0,0, 1,0,0, 1,0,0,//红色——面5
        1,0,0, 1,0,0, 1,0,0, 1,0,0, 1,0,0, 1,0,0 //红色——面6
    ]);
    /**
     *顶点法向量数组normalData
     **/
    var normalData = new Float32Array([
        0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,//z轴正方向——面1
        1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,//x轴正方向——面2
        0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,//y轴正方向——面3
        -1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,//x轴负方向——面4
        0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,//y轴负方向——面5
        0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1,0,0,-1//z轴负方向——面6
    ]);
    /**
     创建缓冲区buffer，传入顶点位置数据data
     **/
    var normalBuffer=gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER,normalBuffer);
    gl.bufferData(gl.ARRAY_BUFFER,normalData,gl.STATIC_DRAW);
    gl.vertexAttribPointer(a_normal,3,gl.FLOAT,false,0,0);
    gl.enableVertexAttribArray(a_normal);
    /**
     创建缓冲区colorBuffer，传入顶点颜色数据colorData
     **/
    var colorBuffer=gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER,colorBuffer);
    gl.bufferData(gl.ARRAY_BUFFER,colorData,gl.STATIC_DRAW);
    gl.vertexAttribPointer(a_color,3,gl.FLOAT,false,0,0);
    gl.enableVertexAttribArray(a_color);
    /**
     创建缓冲区buffer，传入顶点位置数据data
     **/
    var buffer=gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER,buffer);
    gl.bufferData(gl.ARRAY_BUFFER,data,gl.STATIC_DRAW);
    gl.vertexAttribPointer(aposLocation,3,gl.FLOAT,false,0,0);
    gl.enableVertexAttribArray(aposLocation);
    /**执行绘制之前，一定要开启深度测试，以免颜色混乱**/
    gl.enable(gl.DEPTH_TEST);
    /**
     * 传入绕x轴旋转矩阵数据
     ***/
    var angle = Math.PI/4;//旋转角度
    var sin = Math.sin(angle);
    var cos = Math.sin(angle);
    var mxArr = new Float32Array([1,0,0,0,  0,cos,-sin,0,  0,sin,cos,0,  0,0,0,1]);
    gl.uniformMatrix4fv(mx, false, mxArr);

    /**
     * 不同位置相同立方体绘制函数
     ***/
    function drawTx(x) {//x变量表示沿着x轴的平移距离
        //旋转矩阵传入矩阵
        var TxArr = new Float32Array([1,0,0,0,  0,1,0,0,  0,0,1,0,  x,0,0,1]);
        gl.uniformMatrix4fv(Tx, false, TxArr);
        /**执行绘制命令**/
        // gl.drawArrays(gl.TRIANGLES,0,36);
    }

    var angle = Math.PI/4;//起始角度
    var angleSpeed = Math.PI/3000;//角速度Math.PI/3000弧度每毫秒
    var T0 = new Date();//上次时间
    function draw() {
        gl.clear(gl.COLOR_BUFFER_BIT);//清空画布上一帧图像
        /**时间计算**/
        var T1 = new Date();//本次时间
        var t = T1-T0;//时间差（t的单位ms）
        T0 = T1;//把本次时间赋值给上次时间
        /**
         * 立方体绕y轴旋转
         ***/
        angle += t*angleSpeed;//时间差乘以角速度
        var sin = Math.sin(angle);//旋转角度正弦值
        var cos = Math.cos(angle);//旋转角度余弦值
        var myArr = new Float32Array([cos,0,-sin,0,  0,1,0,0,  sin,0,cos,0,  0,0,0,1]);
        gl.uniformMatrix4fv(my, false, myArr);
        requestAnimationFrame(draw);
        /**执行绘制命令**/
        // drawTx(0.5);//绘制立方体1
        // drawTx(-0.5);//绘制立方体2
        var TxArr = new Float32Array([1,0,0,0,  0,1,0,0,  0,0,1,0,  0.5,0,0,1]);
        gl.uniformMatrix4fv(Tx, false, TxArr);
        gl.drawArrays(gl.TRIANGLES,0,36);

        var myArr = new Float32Array([1,0,0,0,  0,1,0,0, 0,0,1,0,  0,0,0,1]);
        gl.uniformMatrix4fv(my, false, myArr);
        var TxArr2 = new Float32Array([1,0,0,0,  0,1,0,0,  0,0,1,0,  -0.5,0.5,0.1,1]);
        gl.uniformMatrix4fv(Tx, false, TxArr2);
        gl.drawArrays(gl.TRIANGLES,0,36);
    }
    draw();
}


    /**
     初始化函数initShader()
     **/
function initShader(gl,vertexShaderSource,fragmentShaderSource){
    var vertexShader = gl.createShader(gl.VERTEX_SHADER);
    var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(vertexShader,vertexShaderSource);
    gl.shaderSource(fragmentShader,fragmentShaderSource);
    gl.compileShader(vertexShader);
    gl.compileShader(fragmentShader);
    var program = gl.createProgram();
    gl.attachShader(program,vertexShader);
    gl.attachShader(program,fragmentShader);
    gl.linkProgram(program);
    gl.useProgram(program);
    return program;
}
main()
